筆記目錄

Skip to content

Elasticsearch 的 Dynamic Field Mapping 注意事項

TLDR

  • 正式環境強烈建議使用明確對應 (Explicit Mapping) 以確保效能與儲存效率。
  • 動態對應 (Dynamic Mapping) 會導致字串欄位產生 textkeyword 雙重索引,造成儲存空間浪費。
  • 特殊功能(如地理位置、巢狀物件、自訂分析器)無法透過動態對應自動啟用,必須手動定義。
  • 過度依賴動態對應會引發 Mapping Explosion,導致索引欄位數量超過上限 (預設 1000 個)。
  • 建議將 dynamic 參數設定為 falsestrict 以防止索引結構失控。

動態欄位對應的誤區

在 Elasticsearch 中,雖然動態對應 (Dynamic Mapping) 提供了開發初期的便利性,但在正式環境中卻隱藏著多項風險。

1. 字串型別導致儲存空間膨脹

什麼情況下會遇到這個問題: 當資料庫自動推斷字串欄位型別時。

Elasticsearch 預設會將字串同時儲存為 textkeyword 型別。text 用於全文檢索,keyword 用於精確比對與聚合。這種雙重索引機制會導致儲存空間大幅增加。若非必要,應明確定義欄位型別以節省空間。

2. 特殊功能無法自動啟用

什麼情況下會遇到這個問題: 當需要使用地理位置、巢狀結構或自訂分析器時。

動態對應僅能處理基礎型別,無法識別特定需求:

  • 地理位置:若未預先定義為 geo_pointgeo_shape,系統會將其視為普通 object,導致無法使用地理查詢 API。
  • 巢狀物件:動態對應會將 nested 物件處理為扁平化的 object,導致陣列內部的物件無法正確查詢。
  • 自訂分析器:動態對應一律使用預設的 standard analyzer,無法套用中文分詞或同義詞處理。

3. Mapping Explosion 的風險

什麼情況下會遇到這個問題: 當資料來源包含大量不固定的欄位名稱(如使用者自訂欄位)時。

若索引中欄位數量過多,會導致記憶體消耗激增。Elasticsearch 預設限制每個索引最多 1000 個欄位,一旦超過此限制,系統將拒絕寫入新文件。


Dynamic Mapping 的型別對應規則

Elasticsearch 根據資料內容自動推斷型別的規則如下:

JSON 資料型別Elasticsearch 型別 ("dynamic":"true")Elasticsearch 型別 ("dynamic":"runtime")
null不新增欄位不新增欄位
truefalsebooleanboolean
doublefloatdouble
longlonglong
objectobject不新增欄位
array取決於陣列中第一個非 null取決於陣列中第一個非 null
通過日期檢測的 stringdatedate
通過數字檢測的 stringfloatlongdoublelong
未通過 datenumeric 檢測的 stringtext 並帶有 .keyword 子欄位keyword

Dynamic 參數的設定選項

為了控管索引結構,建議根據場景調整 dynamic 參數:

  • true (預設值):新欄位自動加入 mapping。適合開發階段,不建議用於正式環境。
  • runtime:新欄位以 runtime fields 形式存在,不進行索引,查詢時即時計算。適合不常查詢的欄位,節省儲存空間但查詢效能較差。
  • false:忽略新欄位。資料仍會出現在 _source 中,但無法被搜尋或索引。可有效防止 Mapping Explosion。
  • strict:偵測到新欄位時直接拋出例外並拒絕寫入。這是最嚴格的控制方式,適合結構要求極高的正式環境。

結論

雖然動態對應功能方便,但在正式環境中,建議事先規劃好 Schema 並使用明確對應 (Explicit Mapping)。這能確保儲存空間、查詢效能與功能需求達到最佳平衡,並避免日後因結構變更而必須重新索引 (Reindex) 的高昂成本。


異動歷程

  • 2025-10-04 初版文件建立。